
def logPacketData(data):
    # Comment out to display packet log data
    return
    lines = len(data)/16
    if lines*16 != len(data): lines=lines+1
    for i in range(lines):
        d = tuple(data[16*i:16*i+16])
        hex = map(lambda x: "%02X"%ord(x),d)
        text = map(lambda x: (len(repr(x))>3 and '.') or x, d)
        log.msg(' '.join(hex)+ ' '*3*(16-len(d)) +''.join(text))
    log.msg('')

def bitstostr(num, size):
    bitstring = ''
    if num < 0: return
    if num == 0: return '0'*size
    cnt = 0
    while cnt < size:
        bitstring = str(num % 2) + bitstring
        num = num >> 1
        cnt = cnt + 1
    return bitstring

def SNAC(fam,sub,id,data,flags=[0,0]):
    head=struct.pack("!HHBBL",fam,sub,
                     flags[0],flags[1],
                     id)
    return head+str(data)

def readSNAC(data):
    try:
        if len(data) < 10: return None
        head=list(struct.unpack("!HHBBL",data[:10]))
        datapos = 10
        if 0x80 & head[2]:
            # Ah flag 0x8000, this is some sort of family indicator, skip it,
            # we don't care.
            sLen,id,length = struct.unpack(">HHH", data[datapos:datapos+6])
            datapos = datapos + 6 + length
        return head+[data[datapos:]]
    except struct.error:
        return None

def oldICQCommand(commandCode, commandData, username, sequence):
    """
    Packs a command for the old ICQ server.
    commandCode (int) - the code of the command,
    commandData - the data payload of the command.
    username (str) - The UIN of the sender
    sequence (int) - The lower word of the SNAC ID that encapsulates the command.
    """
    header = "<HLHH"
    head = struct.pack(header,
                       struct.calcsize(header) + len(commandData) - 2,
                       int(username),
                       commandCode,
                       sequence & 0xffff)
    return head + commandData

def TLV(type,value=''):
    head=struct.pack("!HH",type,len(value))
    return head+str(value)

def readTLVs(data,count=None):
    dict={}
    while data and len(dict)!=count:
        head=struct.unpack("!HH",data[:4])
        dict[head[0]]=data[4:4+head[1]]
        data=data[4+head[1]:]
    if count == None:
        return dict
    return dict,data

def encryptPasswordMD5(password,key):
    m=md5.new()
    m.update(key)
    m.update(md5.new(password).digest())
    m.update("AOL Instant Messenger (SM)")
    return m.digest()

def encryptPasswordICQ(password):
    key=[0xF3,0x26,0x81,0xC4,0x39,0x86,0xDB,0x92,0x71,0xA3,0xB9,0xE6,0x53,0x7A,0x95,0x7C]
    bytes=map(ord,password)
    r=""
    for i in range(len(bytes)):
        r=r+chr(bytes[i]^key[i%len(key)])
    return r

def dehtml(text):
    if (not text):
        text = ""

    # In HTML, line breaks are just whitespace. 
    text=re.sub("\n"," ",text)

    # Convert all of the block-level elements into linebreaks
    text=re.sub('</?[Bb][Rr][^>]*>',"\n",text)
    text=re.sub('</?[Pp][^>]*>',"\n",text)
    text=re.sub('</?[Dd][Ii][Vv][^>]*>',"\n",text)

    # Convert inline images to their alt-tags
    text=re.sub('<[Ii][Mm][Gg] +[^>]*alt=["\']([^"\']*)["\'][^>]*>',r"\1",text)
    
    # Turn bold into stars
    text=re.sub('<[Bb]>(.*?)</[Bb]>',r"*\1*",text)
    text=re.sub('<strong>(.*?)</strong>',r"*\1*",text)
    
    # Turn italics into underscores
    text=re.sub('<[Ii]>(.*?)</[Ii]>',r"_\1_",text)
    
    # Turn quotes into, um quotes.
    text=re.sub('<quote[^>]*>(.*?)</quote>',r'"\1"',text)
    
    # Extract links
    text=re.sub('<[Aa] +[^>]*href=["\']([^"\']*)["\'][^>]*>(.*?)</[Aa]>',r"\2 &lt;\1&gt; ",text)
    
    # Convert more than two linebreaks into just two
    text=re.sub("\n\n+","\n\n",text)
    
    # Get rid of any leading or trailing whitespace
    text=re.sub("^[ \n]+","",text)
    text=re.sub("[ \n]+$","",text)

    # Convert clumps of whitespace into just one space
    text=re.sub(" +"," ",text)

    # Remove any remaining HTML elements.
    text=re.sub('<[^>]*>','',text)

    # Convert the entities
    text=string.replace(text,'&gt;','>')
    text=string.replace(text,'&lt;','<')
    text=string.replace(text,'&nbsp;',' ')
    text=string.replace(text,'&amp;','&')
    text=string.replace(text,'&quot;',"'")
    return text

def html(text):
    if (not text):
        text = ""
    text=string.replace(text,'&','&amp;')
    text=string.replace(text,'<','&lt;')
    text=string.replace(text,'>','&gt;')
    text=string.replace(text,"\n","<br>")
    return '<html><body bgcolor="white"><font color="black">%s</font></body></html>'%text

def getIconSum(buf):
    sum = 0L
    i = 0
    buflen = len(buf)
    while i+1 < buflen:
        sum += (ord(buf[i+1]) << 8) + ord(buf[i])
        i += 2

    if i < buflen:
        sum += ord(buf[i])

    sum = ((sum & 0xffff0000L) >> 16) + (sum & 0x0000ffffL)

    return sum

def decode(data, guess=None):
    encodings = ['utf-8','iso-8859-1'] # iso-8859-1 being another name for Latin-1
    if guess is not None:
        if guess in encodings: encodings.remove(guess)
        encodings.insert(0, guess)
    ustring = ""
    
    #Try complete decoding    
    for encoding in encodings:
        try:
            ustring = unicode(data, encoding)
        except (UnicodeError, LookupError):
            continue
        break

    if ustring == "":
        #Well then let's just do our best
        ustring = unicode(data, encodings[0], 'replace')
        
    return ustring
